package threading;



import java.util.concurrent.PriorityBlockingQueue;
//任务类
class MyTask implements Comparable<MyTask>{
    public Runnable runnable;
    //为了方便后续的判定，使用绝对的时间戳
    public long time;
    public MyTask(Runnable runnable,long delay){
        this.runnable = runnable;
        //取当前时刻的时间戳+delay，作为该任务实际执行的时间戳
        this.time = System.currentTimeMillis() + delay;
    }

    @Override
    public int compareTo(MyTask o) {
        //这样写意味着每次取出的是时间最小的元素。
        return (int)(this.time - o.time);
    }
}
//定时器类
class MyTimer{
    //这个结构，带有优先级的阻塞队列，核心数据结构
    private PriorityBlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();

    //创建一个锁对象
    private Object locker = new Object();

    //此处的delay是一个形如3000这样的数字（多长时间之后，执行该任务）
    public void schedule(Runnable runnable,long delay){
        //根据参数，构造MyTask,插入队列即可。
        MyTask myTask = new MyTask(runnable,delay);
        //向队列中插入任务
        queue.put(myTask);

        synchronized (locker){
            locker.notify();
        }
    }


    //在这里构造线程，负责执行具体任务了
    public MyTimer(){
        Thread t = new Thread(()->{
            while(true){
                try {
                    synchronized(locker){
                          MyTask myTask = queue.take();
                          //获取当前系统时间
                          long curTime = System.currentTimeMillis();
                          if(myTask.time <= curTime){
                              //时间到了，可以执行任务了
                              myTask.runnable.run();
                          }else{
                              //时间还没到
                              //把刚才取出的任务，重新塞回队列中
                              queue.put(myTask);
                              //等待的时长为任务执行时间-当前系统时间
                              locker.wait(myTask.time - curTime);
                          }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        });
        t.start();
    }
}
public class ThreadDemo23 {
    public static void main(String[] args) {
        MyTimer myTimer = new MyTimer();
        myTimer.schedule(new Runnable(){
            @Override
            public void run() {
                System.out.println("hello3");
            }
        },3000);
        myTimer.schedule(new Runnable(){
            @Override
            public void run() {
                System.out.println("hello2");
            }
        },2000);
        myTimer.schedule(new Runnable(){
            @Override
            public void run() {
                System.out.println("hello1");
            }
        },1000);

        System.out.println("hello0");

    }

}
